package com.xy.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.transform.Transformers;


import com.xy.dao.IBaseDao;
import com.xy.utils.HibernateUtil;

public class IBaseDaoImpl implements IBaseDao {

  
	public Session getSession() {
		// from hibernateutil get a session if no session then create it
		return HibernateUtil.getSession();
	}

	public <T> Serializable save(T entity) {
		// TODO Auto-generated method stub
		Serializable id = getSession().save(entity);
		getSession().flush();
		return id;
		/*
		 * try { Serializable id = getSession().save(entity);
		 * getSession().flush(); if (logger.isDebugEnabled()) {
		 * logger.debug("保存实体成功," + entity.getClass().getName()); } return id; }
		 * catch (RuntimeException e) { logger.error("保存实体异常", e); throw e; }
		 */
	}

	public <T> void batchSave(List<T> entities) {
		// TODO Auto-generated method stub
		for (int i = 0; i < entities.size(); i++) {
			getSession().save(entities.get(i));
			if (i % 20 == 0) {
				getSession().flush();
			}
			getSession().flush();
			getSession().clear();
		}
	}

	public <T> void saveOrUpdate(T entity) {
		// TODO Auto-generated method stub
		getSession().saveOrUpdate(entity);
		getSession().flush();
	}

	public <T> void delete(T entity) {
		// TODO Auto-generated method stub
		getSession().delete(entity);
		getSession().flush();
	}

	public <T> void batchDelete(Collection<T> entities) {
		// TODO Auto-generated method stub
		for (T t : entities) {
			delete(t);
		}
	}

	public <T> void deleteById(Class<T> entityName, Serializable id) {
		// TODO Auto-generated method stub
		delete(get(entityName, id));
	}

	public <T> void deleteAll(Class<T> entityName) {
		// TODO Auto-generated method stub
		String hql = "delete from " + entityName.getName();
		Query query = this.getSession().createQuery(hql);
		query.executeUpdate();
	}

	public <T> void update(T entity) {
		// TODO Auto-generated method stub
		getSession().update(entity);
		getSession().flush();
	}

	public <T> void batchUpdate(List<T> entitys) {
		// TODO Auto-generated method stub
		for (int i = 0; i < entitys.size(); i++) {
			getSession().update(entitys.get(i));
			if (i % 20 == 0) {
				// 20个对象后才清理缓存，写入数据�?
				getSession().flush();
				getSession().clear();
			}
		}
		// �?后清理一�?----防止大于20小于40的不保存
		getSession().flush();
		getSession().clear();
		/*
		 * for(T t:entitys){ update(t); }
		 */
	}

	public int updateBySqlString(String sql) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(sql);
		return query.executeUpdate();
	}

	public <T> T load(Class<T> entityName, Serializable id) {
		// TODO Auto-generated method stub
		return (T) getSession().load(entityName, id);
	}

	public <T> List<T> loadAll(Class<T> entityClass) {
		// TODO Auto-generated method stub
		String hql = "from " + entityClass.getName();
		Query query = this.getSession().createQuery(hql);
		return query.list();
	}

	public <T> T get(Class<T> entityName, Serializable id) {
		// TODO Auto-generated method stub
		return (T) getSession().get(entityName, id);
	}

	public <T> T getEntity(Class<T> entityName, Serializable id) {
		// TODO Auto-generated method stub
		T t = (T) getSession().get(entityName, id);
		if (t != null) {
			getSession().flush();
		}
		return t;
	}

	public <T> List<T> getAll(Class<T> entityName) {
		// TODO Auto-generated method stub
		String hql = "from " + entityName.getName();
		Query query = this.getSession().createQuery(hql);
		return query.list();
	}

	public <T> T getSingleByProperty(Class<T> entityName, String propertyName,
			Object value) {
		// TODO Auto-generated method stub
		T t = null; 
		String hql = "from " + entityName.getName() + " where " + propertyName + " =:value ";
		Query query = this.getSession().createQuery(hql);
		query.setParameter("value", value);
		List<T> list = query.list();
		if (list.size() == 1) {
			t = list.get(0);
		}
		return t;
	}

	public <T> T getSingleByHQL(String hqlString) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		return (T) query.uniqueResult();
	}

	public <T> T getSingleByHQL(String hqlString, Object... values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return (T) query.uniqueResult();
	}

	public <T> T getSingleByHQL(String hqlString, Map<String, Object> values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		if (values != null && values.size() > 0) {
			for (Entry<String, Object> p : values.entrySet()) {
				query.setParameter(p.getKey(), p.getValue());
			}
		}
		return (T) query.uniqueResult();
	}

	public <T> T getSingleBySQL(String sqlString, Class<T> entityName) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createSQLQuery(sqlString).setResultTransformer(Transformers.aliasToBean(entityName));
		return (T) query.uniqueResult();
	}

	public <T> T getSingleBySQL(String sqlString, Class<T> entityName,
			Object... values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createSQLQuery(sqlString).setResultTransformer(Transformers.aliasToBean(entityName));
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return (T) query.uniqueResult();
	}

	public <T> T getSingleBySQL(String sqlString, Class<T> entityName,
			Map<String, Object> values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createSQLQuery(sqlString).setResultTransformer(Transformers.aliasToBean(entityName));
		if (values != null && values.size() > 0) {
			for (Entry<String, Object> p : values.entrySet()) {
				query.setParameter(p.getKey(), p.getValue());
			}
		}
		return (T) query.uniqueResult();
	}

	public <T> List<T> getListByProperty(Class<T> entityName,
			String propertyName, Object value) {
		// TODO Auto-generated method stub
		String hql = "from " + entityName.getName() + " where " + propertyName +" =:value";
		Query query = this.getSession().createQuery(hql);
		query.setParameter("value", value);
		return query.list();
	}

	public <T> List<T> getListByHQL(String hqlString) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		return query.list();
	}

	public <T> List<T> getListByHQL(String hqlString, Object... values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return query.list();
	}

	public <T> List<T> getListByHQL(String hqlString, Map<String, Object> values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		if (values != null && values.size() > 0) {
			for (Entry<String, Object> p : values.entrySet()) {
				query.setParameter(p.getKey(), p.getValue());
			}
		}
		return query.list();
	}

	public <T> List<T> getListBySQL(String sqlString, Class<T> entityName) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(sqlString).setResultTransformer(Transformers.aliasToBean(entityName));
		return query.list();
	}

	public <T> List<T> getListBySQL(String sqlString, Class<T> entityName,
			Object... values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(sqlString).setResultTransformer(Transformers.aliasToBean(entityName));
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return query.list();
	}

	public <T> List<T> getListBySQL(String sqlString, Class<T> entityName,
			Map<String, Object> values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(sqlString).setResultTransformer(Transformers.aliasToBean(entityName));
		if (values != null && values.size() > 0) {
			for (Entry<String, Object> p : values.entrySet()) {
				query.setParameter(p.getKey(), p.getValue());
			}
		}
		return query.list();
	}

	public <T> List<T> getListbySql(String sql) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(sql);
		return query.list();
	}

	public <T> List<T> getByPropertyisOrder(Class<T> entityClass,
			String propertyName, Object value, boolean isAsc) {
		// TODO Auto-generated method stub
		String hql = "from " + entityClass.getName() + " where " + propertyName + " =:value order by :order";
		Query query = this.getSession().createQuery(hql);
		query.setParameter("value", value);
		if(isAsc){
			query.setParameter("order", "asc");
		}else
			query.setParameter("order", "desc");
		return query.list();
	}

	public Map<Object, Object> getHashMapbyHql(String hql) {
		// TODO Auto-generated method stub
		Query query = getSession().createQuery(hql);
		List list = query.list();
		Map<Object, Object> map = new HashMap<Object, Object>();
		for (Iterator iterator = list.iterator(); iterator.hasNext();) {
			Object[] tm = (Object[]) iterator.next();
			map.put(tm[0].toString(), tm[1].toString());
		}
		return map;
	}

	public <T> int getCount(Class<T> entityName) {
		// TODO Auto-generated method stub
		String hql = "from " + entityName.getName();
		Query query = getSession().createQuery(hql);
		return query.list().size();
	}

	public Long getCountByHql(String hql, Object... values) {
		// TODO Auto-generated method stub
		Query query = getSession().createQuery(hql);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
//		return (long) query.list().size();
		return (Long) query.uniqueResult();
	}

	public Long getCountByHql(String hql, Map<String, Object> values) {
		// TODO Auto-generated method stub
		Query query = getSession().createQuery(hql);
		if (values != null && values.size() > 0) {
			for (Entry<String, Object> p : values.entrySet()) {
				query.setParameter(p.getKey(), p.getValue());
			}
		}
		return (long) query.list().size();
//		return (Long) query.uniqueResult();
	}

	public <T> boolean contains(T entity) {
		// TODO Auto-generated method stub
		return getSession().contains(entity);
	}

	public Integer executeHql(String hqlString, Object... values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return query.executeUpdate();
	}

	public Integer executeHql(String hqlString, List<Object> values) {
		// TODO Auto-generated method stub
		Query query = getSession().createQuery(hqlString);
		if (values != null && values.size() > 0) {
			for (int i = 0; i < values.size(); i++) {
				query.setParameter(i, values.get(i));
			}
		}
		return query.executeUpdate();
	}

	public Integer executeHql(String hqlString, Map<String, Object> values) {
		// TODO Auto-generated method stub
		Query query = this.getSession().createQuery(hqlString);
		if (values != null && values.size() > 0) {
			for (Entry<String, Object> p : values.entrySet()) {
				query.setParameter(p.getKey(), p.getValue());
			}
		}
		return query.executeUpdate();
	}

	public Integer executeSql(String sqlString, Object... values) {
		// TODO Auto-generated method stub
		return null;
	}

	public Integer executeSql(String sqlString, List<Object> values) {
		// TODO Auto-generated method stub
		return null;
	}

	public Integer executeSql(String sqlString, Map<String, Object> values) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object executeSqlReturnKey(String sql, Map<String, Object> param) {
		// TODO Auto-generated method stub
		return null;
	}

	public <T> void refresh(T entity) {
		// TODO Auto-generated method stub

	}

	public <T> List<T> executeQuery(String hql, Object[] values) {
		// TODO Auto-generated method stub
		return null;
	}

	public <T> PageResults<T> getPageByFetchedHql(String hql, String countHql,
			int pageNo, int pageSize, Object... values) {
		// TODO Auto-generated method stub
	  PageResults<T> retValue = new PageResults<T>();
      Query query = this.getSession().createQuery(hql);
      if (values != null) {
          for (int i = 0; i < values.length; i++) {
              query.setParameter(i, values[i]);
          }
      }
      int currentPage = pageNo > 1 ? pageNo : 1;
      retValue.setCurrentPage(currentPage);
      retValue.setPageSize(pageSize);
      if (countHql == null) {
          ScrollableResults results = query.scroll();
          results.last();
          retValue.setTotalCount(results.getRowNumber() + 1);// 设置总记录数
      } else {
          Long count = getCountByHql(countHql, values);
          retValue.setTotalCount(count.intValue());
      }
      retValue.resetPageNo();
      List<T> itemList = query.setFirstResult((currentPage - 1) * pageSize)
              .setMaxResults(pageSize).list();
      if (itemList == null) {
          itemList = new ArrayList<T>();
      }
      retValue.setResults(itemList);

      return retValue;
	}

	public <T> PageResults<T> getPageByFetchedHql(String hql, String countHql,
			int pageNo, int pageSize, Map<String, Object> values) {
		// TODO Auto-generated method stub
		return null;
	}


	public Long getCountForJdbc(String sql) {
		// TODO Auto-generated method stub

		//wait to write 		
		return null;
	}

	public <T> List<T> getPageList(DetachedCriteria dc, int firstResult,
			int maxResult) {
		// TODO Auto-generated method stub
		
		return null;
	}

	public List<Map<String, Object>> findForJdbc(String sql, Object... objs) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<Map<String, Object>> findForJdbc(String sql, int page, int rows) {
		// TODO Auto-generated method stub
		return null;
	}

	public Map<String, Object> findOneForJdbc(String sql, Object... objs) {
		// TODO Auto-generated method stub
		return null;
	}

	public <T> List<T> findObjForJdbc(String sql, int page, int rows,
			Class<T> clazz) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<Map<String, Object>> findForJdbcParam(String sql, int page,
			int rows, Object... objs) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public <T> List<T> getByExample(String entityName, Object exampleEntity) {
		// TODO Auto-generated method stub
		
//		wait to write
		return null;
	}

  @Override
  public <T> void commit() {
    // TODO Auto-generated method stub
    Transaction tx = getSession().beginTransaction();
    tx.commit();
  }
}
